package com.haoxuer.discover.activiti.controller.admin;

import com.haoxuer.discover.activiti.data.service.FlowService;
import com.haoxuer.discover.activiti.data.so.FlowSo;
import com.haoxuer.discover.activiti.data.vo.TaskVo;
import com.haoxuer.discover.data.page.Page;
import com.haoxuer.discover.data.page.Pageable;
import com.haoxuer.discover.user.shiro.utils.UserUtil;
import org.activiti.engine.HistoryService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.repository.ProcessDefinition;
import org.activiti.engine.repository.ProcessDefinitionQuery;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.Model;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.zip.ZipInputStream;

@Controller
public class WorkFlowController {

    protected Logger logger = LoggerFactory.getLogger(getClass());
    @Autowired
    protected RepositoryService repositoryService;

    @Autowired
    protected RuntimeService runtimeService;
    @Autowired
    protected TaskService taskService;
    @Autowired
    protected HistoryService historyService;
    @Autowired
    FlowService flowService;

    @RequestMapping("/admin/flow/approve")
    public String approve(String taskid, Integer approval, String note, HttpServletRequest request, ModelMap model) {

        String view = "redirect:/admin/flow/task_list.htm";
        try {
            Map<String, Object> variables = new HashMap<String, Object>();
            variables.put("approval", approval);
            taskService.setVariableLocal(taskid, "note", note);
            taskService.setVariableLocal(taskid, "user", UserUtil.getCurrentUser().getName());

            if (approval == 1) {
                taskService.setVariableLocal(taskid, "state", "同意");
            } else {
                taskService.setVariableLocal(taskid, "state", "不同意");
            }
            taskService.complete(taskid, variables);

        } catch (Exception e) {
            e.printStackTrace();
            view = "/admin/task/edit";
        }
        return view;
    }

    /**
     * 部署
     *
     * @param file
     * @param request
     * @return
     * @throws IOException
     */
    @RequestMapping(value = "/admin/flow/deploy")
    public String deploymentProcessDefinition_zip(@RequestParam("file") MultipartFile file, HttpServletRequest request)
            throws IOException {
        // File upload =
        // (File)file;org.springframework.web.multipart.commons.CommonsMultipartFile
        // cannot be cast to java.io.File
        InputStream upload = file.getInputStream();
        ZipInputStream zipInputStream = new ZipInputStream(upload);
        repositoryService.createDeployment().addZipInputStream(zipInputStream).deploy();
        return "redirect:/admin/flow/view_list.htm";
    }

    @RequestMapping(value = "/admin/flow/image")
    public String image(Model model, String taskid, Pageable pageable, HttpServletRequest request) {
        Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
        model.addAttribute("task", task);
        if (task != null) {
            try {
                ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                        .processInstanceId(task.getProcessInstanceId()).singleResult();

                ProcessDefinition definition = repositoryService.getProcessDefinition(task.getProcessDefinitionId());
                ProcessDefinitionEntity processDefinitionEntity = (ProcessDefinitionEntity) definition;

                String activityId = processInstance.getActivityId();
                ActivityImpl activityImpl = processDefinitionEntity.findActivity(activityId);

                model.addAttribute("x", activityImpl.getX());
                model.addAttribute("y", activityImpl.getY());
                model.addAttribute("width", activityImpl.getWidth());
                model.addAttribute("height", activityImpl.getHeight());
            } catch (Exception e) {

            }

        }
        return "/admin/flow/image";
    }

    /**
     * 读取资源，通过部署ID（部署时使用） 查看图片资源或者xml资源
     *
     * @param processDefinitionId 流程定义
     * @param resourceType        资源类型(xml|image)
     * @throws Exception
     */
    @RequestMapping(value = "/admin/flow/read")
    public void loadByDeployment(@RequestParam("processDefinitionId") String processDefinitionId,
                                 @RequestParam("resourceType") String resourceType, HttpServletResponse response) throws Exception {
        ProcessDefinition processDefinition = repositoryService.createProcessDefinitionQuery()
                .processDefinitionId(processDefinitionId).singleResult();
        String resourceName = "";
        if (resourceType.equals("image")) {
            resourceName = processDefinition.getDiagramResourceName();
        } else if (resourceType.equals("xml")) {
            resourceName = processDefinition.getResourceName();
        }
        InputStream resourceAsStream = repositoryService.getResourceAsStream(processDefinition.getDeploymentId(),
                resourceName);
        byte[] b = new byte[1024];
        int len = -1;
        while ((len = resourceAsStream.read(b, 0, 1024)) != -1) {
            response.getOutputStream().write(b, 0, len);
        }
    }

    @RequestMapping(value = "/admin/flow/task_list")
    public String myTaskList(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
        Page<TaskVo> page = flowService.page(UserUtil.getCurrentUser().getId()+"", pageable, so);
        model.addAttribute("list", page.getContent());
        model.addAttribute("page", page);
        model.addAttribute("so", so);
        return "/admin/flow/my_task_list";
    }

    /**
     * 系统中部署了多少工作流
     *
     * @param model
     * @param request
     * @return
     */
    @RequestMapping(value = "/admin/flow/view_list")
    public String processDefinitionList(Model model, HttpServletRequest request) {
        /*
		 * 只读取表单：leave-formkey
		 */
        ProcessDefinitionQuery query = repositoryService.createProcessDefinitionQuery().latestVersion()
                .orderByProcessDefinitionName().desc();
        List<ProcessDefinition> list = query.list();
        model.addAttribute("list", list);

        return "/admin/flow/list";
    }

    @RequestMapping(value = "/admin/flow/records")
    public String records(Model model, String businessKey, HttpServletRequest request) {
        model.addAttribute("records", flowService.records(businessKey));

        return "/admin/flow/records";
    }

    @RequestMapping(value = "/admin/flow/task")
    public String task(Model model, String taskid, HttpServletRequest request, Integer type) {
        Task task = taskService.createTaskQuery().taskId(taskid).singleResult();
        model.addAttribute("task", task);
        model.addAttribute("type", type);

        model.addAttribute("model", taskService.getVariables(taskid));

        ProcessInstance processInstance = runtimeService.createProcessInstanceQuery()
                .processInstanceId(task.getProcessInstanceId()).singleResult();
        model.addAttribute("records", flowService.records(processInstance.getBusinessKey()));

        return "/admin/flow/taskview";
    }

    @RequestMapping(value = "/admin/flow/task_list_all")
    public String taskList(Model model, FlowSo so, Pageable pageable, HttpServletRequest request) {
        Page<TaskVo> page = flowService.page(pageable, so);
        model.addAttribute("list", page.getContent());
        model.addAttribute("page", page);
        model.addAttribute("so", so);
        return "/admin/flow/task_list";
    }

    @RequestMapping(value = "/admin/flow/view_add")
    public String view_add(Model model) {

        return "admin/flow/add";
    }

}
